/*=+--+=#=+--     Unmanned Aerial System Management Software      --+=#=+--+=#*\
|          Copyright (C) 2011 Regents of the University of Colorado.           |
|                             All Rights Reserved.                             |

     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License version 2 as
     published by the Free Software Foundation.

     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.

     You should have received a copy of the GNU General Public License
     along with this program.  If not, see <http://www.gnu.org/licenses/>.

            Jack Elston                       Cory Dixon                        
|           elstonj@colorado.edu              dixonc@colorado.edu              |
|                                                                              |
\*=+--+=#=+--                 --+=#=+--+=#=+--                    --+=#=+--+=#*/

// File: serialTest.cpp
// Author: Cory Dixon
// Date: 2/27/01
//
// Program to test the serial port both in Unix
// and VxWorks
//

#include <unistd.h>
#include <signal.h>
#include <iostream.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <fcntl.h>

#include "String.h"
#include "serial.h"
#include "timeLib.h"
#include "fileLog.h"
#include "type_defs.h"

// functions
void usage();		  // prints usage description
void exitsignal( int signal );   // catches and deals with exiting signals
void myclose(int value);    // closes open fd and exits

void run();
void closeConnection() ;

//
// Global Data
//
SerialPort *serial;
FileLog serialLog("log/serialLog",FileLog::CREATE);
FileLog parseLog("log/serialLog",FileLog::READ);

bool parse = 0;
LogFileStruct line;
int bytesRead;
struct tm tmTime;

//----------------------------------------------------------
// Main function
//----------------------------------------------------------

int main(int argc, char *argv[])
{
	String devStr = "/dev/ttyS0";
	String baudStr = "9600";

	// used for getopt to get otions from arguments
	extern int optind;

	 // catch signals
	signal( SIGINT, exitsignal);

	int c;
	while ((c=getopt(argc,argv,"h")) != EOF) switch( (char)c)
	   {
		case 'h':
			usage();
			exit(EXIT_SUCCESS);
		case 'p':
			parse = 1;	
			break;
		default:
			cout << "Unknown arg " << argv[optind - 1] << endl;
			usage();
			exit(EXIT_SUCCESS);
	}

	if( !parse ) {
		if( optind + 2  ==  argc) {
			devStr = String(argv[optind]); 
			baudStr = String(argv[optind + 1]);	
		} else {
			usage();
			exit(EXIT_SUCCESS);
		}

		// open serial port
		serial = new SerialPort(devStr.c_str(),baudStr.c_str());
		assert(serial != NULL);

		if( serial->init() != SerialPort::Connected ){
			printf("Could not open serial port\n");
			exit(EXIT_FAILURE);
		}

		// set serial to be nonblocking 
		//serial->setBlocking();
		serial->setLocal();
		serial->setLine();

		if (! serialLog.open() ) {
			cout << "Could not open " << serialLog.getFileName() << endl;
			perror("serialLog.open()");
		}

		run();
	} else {
		if (! parseLog.open() ) {
			cout << "Could not open " << parseLog.getFileName() << endl;
			perror("parseLog.open()");
		}
		// after first read, can get time struct tm
		bytesRead = parseLog.read( line );
		tmTime = parseLog.getTime();

		cout << "File: " << inFileStr << " - " << parseLog.fileSize() << " [bytes]" << endl
			<< "-------------------------" << endl
			<< " year=" << tmTime.tm_year + 1900
			<< " month=" << tmTime.tm_mon + 1
			<< " day=" << tmTime.tm_mday 
			<< " hour=" << tmTime.tm_hour 
			<< " min=" << tmTime.tm_min 
			<< " sec=" << tmTime.tm_sec << endl;

		while( (bytesRead = imuLog.read( line )) > 0 ) {
			ProcessOutput(line.bytes, line.numOfBytes);
		}
	}
	// exit
	myclose(EXIT_SUCCESS);
}

//----------------------------------------------------------
// print usage
//----------------------------------------------------------
void usage()
{
	printf("usage: serialLog {-h} [ -p | dev baud ]\n");
}

//----------------------------------------------------------
// catch exit signals
//----------------------------------------------------------
void exitsignal( int signal )
{
	printf("Caught signal %d ... exiting\n",signal);
	fflush(stdout);
}

//----------------------------------------------------------
// close down properly
//----------------------------------------------------------
void myclose(int value)
{
	closeConnection();	 

	delete serial;

	exit(value);
}

//----------------------------------------------------------
// close connection
//----------------------------------------------------------
void closeConnection() 
{
	cout << "Closing connection ... ";

	// send disconnect command to host
	if( serial != NULL) {
		// close serial
		serial->close();

		// print serialet statistics
		serial->printStats();
	}

	// close log
	if ( ! serialLog.close() ) {
		cout << "Could not close" << serialLog.getFileName() << endl;
		perror("serialLog.close()");
	}   
	cout << "Log File:" << endl << "--------------------" << endl
		<< "\tbytesWritten= " << serialLog.bytesWritten()
		<< "\tfileSize= " << serialLog.fileSize()
		<< endl << endl;

	cout << "closed" << endl;
}

//----------------------------------------------------------
// Act on received commands
//----------------------------------------------------------
void run()
{
	SerialPort::SerialWait serialWait;
	int num;
	char rxBuf[256];

	while( 1 )
	{

		// wait for input, timeout at 1000 milli-sec
		serialWait = serial->wait(1000);

		if( serialWait == SerialPort::WAIT_TIMEOUT) {
			cout << "serial->wait timedout" << endl;
		} else if(serialWait == SerialPort::WAIT_INT) {
			cout << "serial->wait interrupted" << endl;
			myclose(0);
		}
		else if(serialWait == SerialPort::WAIT_ERROR)
			cout << "serial->wait error" << endl;
		else if( serialWait == SerialPort::WAIT_DATA) {
			// cout << "Reading data" << endl;
			// get the command from client
			num = serial->read((char *)rxBuf, CMD_MAX_SIZE);

			if( num > 0) {
				serialLog.write((char *)rxBuf, num);
			} else {
				if( num == 0)
					cout << "Read 0 bytes" << endl;
				else if( errno != EWOULDBLOCK || errno != EINTR)
					perror("serverMode() - bad read from client");
			}
		}
	} // end of while
}
